﻿<# 
.SYNOPSIS 
    Create a new PeopleSoft Application Server domain.
.DESCRIPTION 
    The command New-PsftDomain will create a new PeopleSoft Application Server domain with the name specified.
    The command accepts values for each of the initial configuration parameters.
    If not specified, a default value will be configured.
.NOTES 
    File Name  : New-PsftDomain.ps1 
    Author     : Scott Kearney - scott@kearney.tk 
    Requires   : PowerShell V3 
.EXAMPLE 
    New-PsftDomain -PS_HOME C:\psoft\PS_HOME -PS_CFG_HOME C:\psoft\PS_CFG_HOME -NewDomain DOMAIN2 -Template Small
    Creates a new small PeopleSoft Application Server domain DOMAIN2 with default values.
.EXAMPLE 
    New-PsftDomain -PS_HOME C:\psoft\PS_HOME -PS_CFG_HOME C:\psoft\PS_CFG_HOME -NewDomain DOMAIN2 -Template Large -DatabaseName DEMO -DatabaseType Oracle -UserId PS -UserPassword PS
    Creates a new large PeopleSoft Application Server domain DOMAIN2 with the database information configured.
.PARAMETER PS_HOME
    The full path to the PS_HOME directory for this domain.
.PARAMETER PS_CFG_HOME
    The full path to the PS_CFG_HOME directory for this domain.
.PARAMETER NewDomain
    The name of the domain to be created.
.PARAMETER Template    The domain template to be used in creating the domain.    Choose from Small, Medium, Large, or Developer..PARAMETER DatabaseName    The name of the database to connect to.    Must be 8 characters or less..PARAMETER DatabaseType    The type of database that the server will connect to.    Choose from Oracle, Informix, Sybase, Microsoft, DB2 z/OS, or DB2 Unix..PARAMETER UserId    The PeopleSoft user id that will be used to connect to the database..PARAMETER UserPassword    The password for the PeopleSoft user..PARAMETER AddToPath    Any paths that should be added to the PATH environment variable.    This list must contain a list of paths separated by semicolons..PARAMETER ConnectId    The connect id for the database..PARAMETER ConnectPassword    The connect password for the database..PARAMETER DatabaseServerName    If your RDBMS requires it, the name of the server hosting the database..PARAMETER DomainConnectionPassword    If specified, the password which will be required to interact with the application server..PARAMETER EncryptPasswords    Whether to encrypt the passwords in the configuration file or not..PARAMETER WSLPort    The Workstation listener port..PARAMETER JSLPort    The Jolt session listener port..PARAMETER JRADPort    The Jolt internet relay listener port..PARAMETER EnvironmentSettings
    Advanced feature. Specifies domain environment variable settings.
#> 
function New-PsftDomain
{
    [CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Medium')]
    Param
    (
        # The full path to the PS_HOME directory for this domain.
        # See http://docs.oracle.com/cd/E41633_01/pt853pbh1/eng/pt/tsvt/concept_UnderstandingPS_HOMEandPS_CFG_HOME-eb7ece.html
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The full path to the PS_HOME directory for this domain.",
                   Position=0)]
        [ValidateScript({Validate_PS_HOME $_})]
        [String]
        $PS_HOME,

        # The full path to the PS_CFG_HOME directory for this domain.
        # See http://docs.oracle.com/cd/E41633_01/pt853pbh1/eng/pt/tsvt/concept_UnderstandingPS_HOMEandPS_CFG_HOME-eb7ece.html
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The full path to the PS_CFG_HOME directory for this domain.",
                   Position=1)]
        [ValidateScript({Validate_PS_CFG_HOME $_})]
        [String]
        $PS_CFG_HOME,

        # The type of server on which to perform the action.
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The type of server on which to perform the action.",
                   Position=2)]
        [ValidateSet("AppServer","PrcsScheduler")]
        $ServerType,

        # The name of the domain to be created.
        # Will be a directory under the PS_CFG_HOME
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The name of the domain to be created.",
                   Position=3)]
        [ValidateScript({Validate_NewDomain $PS_CFG_HOME $ServerType $_})]
        [String]
        $NewDomain,

        # The domain template to be used in creating the domain.        # Choose from Small, Medium, Large, or Developer.
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The domain template to be used in creating the domain.",
                   Position=4)]
        [ValidateSet("Small","Medium","Large","Developer")]
        [String]
        $Template,

        # The name of the database to connect to.        # Must be 8 characters or less.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The name of the database to connect to.",
                   Position=5)]
        [ValidateLength(1,8)]
        [String]
        $DatabaseName = $NewDomain.Substring(0,7),

        # The type of database that the server will connect to.        # Choose from Oracle, Informix, Sybase, Microsoft, DB2 z/OS, or DB2 Unix.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The type of database that the server will connect to.",
                   Position=6)]
        [ValidateSet("Oracle","Informix","Sybase","Microsoft","DB2 z/OS","DB2 Unix")]
        [String]
        $DatabaseType = "Oracle",
        
        # The process scheduler server to register to this instance.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The process scheduler server to register to this instance.",
                   Position=7,
                   ParameterSetName = "PrcsScheduler")]
        [ValidateLength(1,30)]
        [String]
        $PrcsServer = "PSNT",

        # The PeopleSoft user id that will be used to connect to the database.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The PeopleSoft user id that will be used to connect to the database.",
                   Position=8)]
        [ValidateLength(1,30)]
        [String]
        $UserId = "QEDMO",

        # The password for the PeopleSoft user.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The password for the PeopleSoft user.",
                   Position=9)]
        [ValidateLength(0,32)]
        [String]
        $UserPassword = "",
        
        # Any paths that should be added to the PATH environment variable.        # This list must contain a list of paths separated by semicolons.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "Any paths that should be added to the PATH environment variable.",
                   Position=10)]
        [String]
        $AddToPath = "",

        # The connect id for the database.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The connect id for the database.",
                   Position=11)]
        [ValidateNotNullOrEmpty()]
        [ValidateLength(1,8)]
        [String]
        $ConnectId = "people",

        # The connect password for the database.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The connect password for the database.",
                   Position=12)]
        [ValidateLength(0,8)]
        [String]
        $ConnectPassword = "",

        # If your RDBMS requires it, the name of the server hosting the database.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "If your RDBMS requires it, the name of the server hosting the database.",
                   Position=13)]
        [AllowEmptyString()]
        [String]
        $DatabaseServerName = "",

        # The location of the log/output directory.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The location of the log/output directory.",
                   Position=14,
                   ParameterSetName = "PrcsScheduler")]
        [ValidateNotNullOrEmpty()]
        [String]
        $LogOutDir = "%PS_SERVDIR%\log_output",

        # The location of the sqr binaries.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The location of the sqr binaries.",
                   Position=15,
                   ParameterSetName = "PrcsScheduler")]
        [ValidateNotNullOrEmpty()]
        [String]
        $SqrBin = "$PS_HOME\bin\sqr\ORA\binw",

        # The location of the Crystal Reports binaries.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The location of the Crystal Reports binaries.",
                   Position=16,
                   ParameterSetName = "PrcsScheduler")]
        [String]
        $CrystalBin = "",

        # The location of the database connectivity binaries.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The location of the database connectivity binaries.",
                   Position=17,
                   ParameterSetName = "PrcsScheduler")]
        [ValidateNotNullOrEmpty()]
        [String]
        $DBBin = "",

        # If specified, the password which will be required to interact with the application server.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "If specified, the password which will be required to interact with the application server.",
                   Position=18)]
        [ValidateNotNull()]
        [String]
        $DomainConnectionPassword = "",

        # Whether to encrypt the passwords in the configuration file or not.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "Whether to encrypt the passwords in the configuration file or not.",
                   Position=19)]
        [Switch]
        $EncryptPasswords,

        # The Workstation listener port.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The Workstation listener port.",
                   Position=20,
                   ParameterSetName = "AppServer")]
        [ValidateRange(1025,65536)]
        [int]
        $WSLPort = 7000,

        # The Jolt session listener port.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The Jolt session listener port.",
                   Position=21,
                   ParameterSetName = "AppServer")]
        [ValidateRange(1025,65536)]
        [int]
        $JSLPort = 9000,

        # The Jolt internet relay listener port.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   HelpMessage = "The Jolt internet relay listener port.",
                   Position=22,
                   ParameterSetName = "AppServer")]
        [ValidateRange(1025,65536)]
        [int]
        $JRADPort = 9100,

        # Advanced feature
        # Specifies domain environment settings, having the following format:
        # ENVAR_NAME1=ENVVAR_VALUE1#ENVAR_NAME2=ENVVAR_VALUE2
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   Position=23)]
        [String]
        $EnvironmentSettings = ""
        
    )

    Begin
    {
    }
    Process
    {
        # Parse the variables coming from the arguments

        # The $DatabaseType must be converted from the human-readable format to the psadmin.exe format
        switch ($DatabaseType)
        {
            'Oracle'    {$DatabaseTypeTransform = "ORACLE"}
            'Informix'  {$DatabaseTypeTransform = "INFORMIX"}
            'Sybase'    {$DatabaseTypeTransform = "SYBASE"}
            'Microsoft' {$DatabaseTypeTransform = "MICROSFT"}
            'DB2 z/OS'  {$DatabaseTypeTransform = "DB2ODBC"}
            'DB2 Unix'  {$DatabaseTypeTransform = "DB2UNIX"}
            Default     {$DatabaseTypeTransform = "ORACLE"}
        }

        Write-Verbose "DatabaseType: $DatabaseTypeTransform"

        # # $AddToPath is not required, but if it is omitted,
        # # it should be replaced with an empty string indicator.
        # if($AddToPath -eq ""){
        #     $AddToPathTransform = "_____"
        #     Write-Verbose "AddToPath: $AddToPathTransform"
        # } else {
        #     $AddToPathTransform = """$AddToPath"""
        # }
        # 
        # # $DatabaseServerName is not required, but if it is omitted,
        # # it should be replaced with an empty string indicator.
        # if($DatabaseServerName -eq ""){
        #     $DatabaseServerNameTransform = "_____"
        #     Write-Verbose "DatabaseServerName: $DatabaseServerNameTransform"
        # } else {
        #     $DatabaseServerNameTransform = $DatabaseServerName
        # }
        # 
        # # $DomainConnectionPassowrd is not required, but if it is omitted, 
        # # it should be replaced with an empty string indicator.
        # if($DomainConnectionPassword -eq ""){
        #     $DomainConnectionPasswordTransform = "_____"
        #     Write-Verbose "DomainConnectionPassword: $DomainConnectionPasswordTransform"
        # } else {
        #     $DomainConnectionPasswordTransform = $DomainConnectionPassword
        # }
        # 
        # # Choose the encryption argument based on the switch state
        # if($EncryptPasswords){
        #     $EncryptPasswordsTransform = "ENCRYPT"
        # } else {
        #     $EncryptPasswordsTransform = "NOENCRYPT"
        # }
        # 
        # # These directories may have spaces in their path. Enclose in quotes to be safe
        # $LogOutDirTransform = """$LogOutDir"""
        # $SqrBinTransform = """$SqrBin"""
        # $DBBinTransform = """$DBBin"""
        # 
        # # $CrystalBin is not required, but if it is omitted,
        # # it should be replaced with an empty string indicator.
        # if($CrystalBin -eq ""){
        #     $CrystalBinTransform = "_____"
        #     Write-Verbose "CrystalBin: $CrystalBinTransform"
        # } else {
        #     $CrystalBinTransform = """$CrystalBin"""
        # }

        # Choose the encryption argument based on the switch state
        if($EncryptPasswords){
            $EncryptPasswordsTransform = "ENCRYPT"
        } else {
            $EncryptPasswordsTransform = "NOENCRYPT"
        }

        Write-Verbose "EncryptPasswords: $EncryptPasswordsTransform"

        $AddToPathTransform                = SanitizeInput $AddToPath
        $DatabaseServerNameTransform       = SanitizeInput $DatabaseServerName
        $DomainConnectionPasswordTransform = SanitizeInput $DomainConnectionPassword
        $LogOutDirTransform                = SanitizeInput $LogOutDir
        $SqrBinTransform                   = SanitizeInput $SqrBin
        $DBBinTransform                    = SanitizeInput $DBBin
        $CrystalBinTransform               = SanitizeInput $CrystalBin
        
        # Build the $extraCommands argument to create the domain
        switch ($ServerType)
        {
            'AppServer'     {
                                $extraCommands = ("-t $Template " +
                                                  "-s $DatabaseName/$DatabaseTypeTransform/$UserId/$UserPassword/$($NewDomain.ToUpper())/$AddToPathTransform/$ConnectId/$ConnectPassword/$DatabaseServerNameTransform/$DomainConnectionPasswordTransform/$EncryptPasswordsTransform " +
                                                  "-p $WSLPort/$JSLPort/$JRADPort " +
                                                  "-e $EnvironmentSettings")
                            }
            'PrcsScheduler' {
                                $extraCommands = ("-t windows " +
                                                  "-ps $DatabaseName/$DatabaseTypeTransform/$PrcsServer/$UserId/$UserPassword/$ConnectId/$ConnectPassword/$DatabaseServerNameTransform/$LogOutDirTransform/$SqrBinTransform/$AddToPathTransform/$DBBinTransform/$CrystalBinTransform/$DomainConnectionPasswordTransform/$EncryptPasswordsTransform " +
                                                  "-e $EnvironmentSettings")
                            }
            'SearchServer'  {
                                $extraCommands =  "-t $Template"
                            }
            'WebServer'     { }
        }

        # Confirm that the user would like to create a new domain.
        if($PSCmdlet.ShouldProcess($NewDomain,"New-PsftDomain"))
        {   
            # Invoke PSAdmin to create the new domain.
            $PSAdmin = Invoke-PSAdmin -PS_HOME $PS_HOME -PS_CFG_HOME $PS_CFG_HOME -ServerType $ServerType -Domain $NewDomain -Command "create" -ExtraCommands $extraCommands
		}

		$return = $PSAdmin.Result

        return $return
    }
    End
    {
    }
}